import { h, unref } from 'vue';
import type { App, Plugin, reactive } from 'vue';
import { NIcon, NTag } from 'naive-ui';
import { PageEnum } from '@/enums/pageEnum';
import { isObject } from './is/index';
import { cloneDeep } from 'lodash-es';
/**
 * render 图标
 * */
export function renderIcon(icon) {
  return () => h(NIcon, null, { default: () => h(icon) });
}

/**
 * render new Tag
 * */
const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
export function renderNew(type = 'warning', text = 'New', color: object = newTagColors) {
  return () =>
    h(
      NTag as any,
      {
        type,
        round: true,
        size: 'small',
        color,
      },
      { default: () => text }
    );
}

/**
 * 递归组装菜单格式
 */
export function generatorMenu(routerMap: Array<any>) {
  return filterRouter(routerMap).map((item) => {
    const isRoot = isRootRouter(item);
    const info = isRoot ? item.children[0] : item;
    const currentMenu = {
      ...info,
      ...info.meta,
      label: info.meta?.title,
      key: info.name,
      icon: isRoot ? item.meta?.icon : info.meta?.icon,
    };
    // 是否有子菜单，并递归处理
    if (info.children && info.children.length > 0) {
      // Recursion
      currentMenu.children = generatorMenu(info.children);
    }
    return currentMenu;
  });
}

/**
 * 混合菜单
 * */
export function generatorMenuMix(routerMap: Array<any>, routerName: string, location: string) {
  const cloneRouterMap = cloneDeep(routerMap);
  const newRouter = filterRouter(cloneRouterMap);
  if (location === 'header') {
    const firstRouter: any[] = [];
    newRouter.forEach((item) => {
      const isRoot = isRootRouter(item);
      const info = isRoot ? item.children[0] : item;
      info.children = undefined;
      const currentMenu = {
        ...info,
        ...info.meta,
        label: info.meta?.title,
        key: info.name,
      };
      firstRouter.push(currentMenu);
    });
    return firstRouter;
  } else {
    return getChildrenRouter(newRouter.filter((item) => item.name === routerName));
  }
}

/**
 * 递归组装子菜单
 * */
export function getChildrenRouter(routerMap: Array<any>) {
  return filterRouter(routerMap).map((item) => {
    const isRoot = isRootRouter(item);
    const info = isRoot ? item.children[0] : item;
    const currentMenu = {
      ...info,
      ...info.meta,
      label: info.meta?.title,
      key: info.name,
    };
    // 是否有子菜单，并递归处理
    if (info.children && info.children.length > 0) {
      // Recursion
      currentMenu.children = getChildrenRouter(info.children);
    }
    return currentMenu;
  });
}

/**
 * 判断根路由 Router
 * */
export function isRootRouter(item) {
  return item.meta?.alwaysShow != true && item.children?.length === 1;
}

/**
 * 排除Router
 * */
export function filterRouter(routerMap: Array<any>) {
  return routerMap.filter((item) => {
    return (
      (item.meta?.hidden || false) != true &&
      !['/:path(.*)*', '/', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path)
    );
  });
}

export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component);
    if (alias) {
      app.config.globalProperties[alias] = component;
    }
  };
  return component as T & Plugin;
};

/**
 *  找到对应的节点
 * */
let result = null;
export function getTreeItem(data: any[], key?: string | number): any {
  data.map((item) => {
    if (item.key === key) {
      result = item;
    } else {
      if (item.children && item.children.length) {
        getTreeItem(item.children, key);
      }
    }
  });
  return result;
}

/**
 *  找到所有节点
 * */
const treeAll: any[] = [];
export function getTreeAll(data: any[]): any[] {
  data.map((item) => {
    treeAll.push(item.key);
    if (item.children && item.children.length) {
      getTreeAll(item.children);
    }
  });
  return treeAll;
}

// dynamic use hook props
export function getDynamicProps<T, U>(props: T): Partial<U> {
  const ret: Recordable = {};

  Object.keys(props).map((key) => {
    ret[key] = unref((props as Recordable)[key]);
  });

  return ret as Partial<U>;
}

export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
  let key: string;
  for (key in target) {
    src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]);
  }
  return src;
}

/**
 * Sums the passed percentage to the R, G or B of a HEX color
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed part of the color
 */
function addLight(color: string, amount: number) {
  const cc = parseInt(color, 16) + amount;
  const c = cc > 255 ? 255 : cc;
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
}

/**
 * Lightens a 6 char HEX color according to the passed percentage
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed color represented as HEX
 */
export function lighten(color: string, amount: number) {
  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
  amount = Math.trunc((255 * amount) / 100);
  return `#${addLight(color.substring(0, 2), amount)}${addLight(
    color.substring(2, 4),
    amount
  )}${addLight(color.substring(4, 6), amount)}`;
}

// 节流函数
// 思路： 第一次先设定一个变量true，
// 第二次执行这个函数时，会判断变量是否true，
// 是则返回。当第一次的定时器执行完函数最后会设定变量为flase。
// 那么下次判断变量时则为flase，函数会依次运行。
export function throttle(fn, delay = 200) {
  // 首先设定一个变量，在没有执行我们的定时器时为null
  let timer = null;
  return function () {
    // 当我们发现这个定时器存在时，则表示定时器已经在运行中，需要返回
    if (timer) return;
    timer = setTimeout(() => {
      fn.apply(this, arguments);
      timer = null;
    }, delay);
  };
}

// 防抖函数
// 首次运行时把定时器赋值给一个变量， 第二次执行时，
// 如果间隔没超过定时器设定的时间则会清除掉定时器，
// 重新设定定时器， 依次反复， 当我们停止下来时，
// 没有执行清除定时器， 超过一定时间后触发回调函数。
// 参考文档：https://segmentfault.com/q/1010000021145192
export function debounce(fn, delay = 200) {
  let timer;
  return function () {
    const that = this;
    const _args = arguments; // 存一下传入的参数
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(function () {
      fn.apply(that, _args);
    }, delay);
  };
}

export function rebuildData(value, arr, searchKey = 'name', children = 'children') {
  if (!arr) {
    return [];
  }
  const newarr = [];
  arr.forEach((element) => {
    if (element[searchKey].indexOf(value) > -1) {
      const ab = rebuildData(value, element[children]);
      const obj = {
        ...element,
        [children]: ab,
      };
      newarr.push(obj);
    } else {
      if (element[children] && element[children].length > 0) {
        const ab = rebuildData(value, element[children]);
        const obj = {
          ...element,
          [children]: ab,
        };
        if (ab && ab.length > 0) {
          newarr.push(obj);
        }
      }
    }
  });
  return newarr;
}

/**
 * 删除树形结构中所有的空children
 * @param tree
 * @returns {*}
 */
export function deleteNullChildren(tree, childrenKey = 'children') {
  const treeClone = JSON.parse(JSON.stringify(tree));

  return treeClone.filter((item) => {
    if (Array.isArray(item[childrenKey]) && item[childrenKey].length === 0) {
      delete item[childrenKey];
    }
    if (Array.isArray(item[childrenKey]) && item[childrenKey].length > 0) {
      item[childrenKey] = deleteNullChildren(item[childrenKey]);
    }

    return true;
  });
}

/**
 * 清楚参数为空字符传的参数
 * @param vue
 * @param params
 */
export function structureParams(params = {}) {
  const dict = JSON.parse(JSON.stringify(params));
  for (const item in dict) {
    if (dict[item] === '' || dict[item] === null) {
      dict[item] = undefined;
    }
  }

  return dict;
}

/**
 * 文件导出方法
 * @param fileName 文件名
 * @param fileBlob 文件blob流 或者文件 url
 */
export function exportFile(fileName, fileBlob) {
  const a = document.createElement('a'); // 创建一个<a></a>标签

  if (typeof fileBlob === 'string') {
    // window.open(fileBlob)
    a.href = fileBlob;
  } else {
    if (fileBlob instanceof Blob) {
      a.href = URL.createObjectURL(fileBlob);
    } else {
      a.href = URL.createObjectURL(new Blob(fileBlob));
    }
  }

  a.download = fileName; // 设置文件名
  a.target = '_blank';
  a.style.display = 'none'; // 障眼法藏起来a标签
  document.body.appendChild(a); // 将a标签追加到文档对象中
  a.click(); // 模拟点击了a标签，会触发a标签的href的读取，浏览器就会自动下载了
  a.remove(); // 一次性的，用完就删除a标签
}

/**
 * 获取树中所有底层子节点
 */
export function getTreeBaseData(tree, children = 'children', key = 'id') {
  const subTree = []; // test存放所有子节点的数组
  // 第一步骤：子节点放在一个数组中
  const requestList = (data) => {
    data &&
      data.map((item) => {
        if (item[children] && item[children].length > 0) {
          requestList(item[children]);
        } else {
          // @ts-ignore
          subTree.push(item[key]);
        }
        return null;
      });
    return subTree;
  };

  return requestList(tree);
}

/**
 * 获取数组中的交集
 * @param getArrIntersection
 * @param Arr
 * @returns {*[]}
 */
export function getArrIntersection(uniqueArr, Arr) {
  const uniqueChild = [];
  for (const i in Arr) {
    for (const k in uniqueArr) {
      if (uniqueArr[k] === Arr[i]) {
        // @ts-ignore
        uniqueChild.push(uniqueArr[k]);
      }
    }
  }
  return uniqueChild;
}

/**
 * 获取数组差集
 * @param arr1 求差数组
 * @param arr2 被球差
 */
export function getArrDiff(arr1, arr2) {
  const diff = arr1.filter((item) => {
    return !new Set(arr2).has(item);
  });

  return diff;
}

/**
 * 构造下拉选项字段
 */
export function structureSelectOptions(arr, option, canUesOriginal = false) {
  return arr.map((item) => {
    let resItem = {};
    canUesOriginal && (resItem = { ...item });
    for (const key in option) {
      resItem[key] = item[option[key]];
    }
    return resItem;
  });
}
